package cn.lg.soar.general.service.impl;

import cn.lg.soar.database.base.service.impl.BaseServiceImpl;
import cn.lg.soar.general.api.enums.FileStorageStatusEnum;
import cn.lg.soar.general.config.GeneralCacheKey;
import cn.lg.soar.general.entity.FileStorage;
import cn.lg.soar.general.mapper.BizFileMapper;
import cn.lg.soar.general.s3.FileTemplate;
import cn.lg.soar.general.service.IFileStorageService;
import cn.lg.soar.general.manager.FileTemplateManager;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.Collection;

/**
 * 文件仓库
 * @author luguoxiang
 * @since 2024-03-01
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
@Service
public class FileStorageServiceImpl extends BaseServiceImpl<BizFileMapper.FileStorageMapper, FileStorage> implements IFileStorageService {

    @Autowired
    private FileTemplateManager uploadTemplateManager;

    @Cacheable(value = GeneralCacheKey.FILE_STORAGE, key = "#id")
    @Override
    public FileStorage getById(Serializable id) {
        return super.getById(id);
    }

    @CacheEvict(value = GeneralCacheKey.FILE_STORAGE, key = "'default'")
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean save(FileStorage entity) {
        handleDefaulted(entity);
        return super.save(entity);
    }

    @Caching(evict = {
            @CacheEvict(value = GeneralCacheKey.FILE_STORAGE, key = "#entity.id"),
            @CacheEvict(value = GeneralCacheKey.FILE_STORAGE, key = "'default'")
    })
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateById(FileStorage entity) {
        handleDefaulted(entity);
        uploadTemplateManager.removeTemplate(entity.getId());
        return super.updateById(entity);
    }

    @Override
    public boolean removeByIds(Collection<?> list) {
        Cache cache = cacheManager.getCache(GeneralCacheKey.FILE_STORAGE);
        if (cache != null) {
            // 逐条清理缓存
            for (Object o : list) {
                cache.evict(o);
                uploadTemplateManager.removeTemplate(o);
            }
        }
        return super.removeByIds(list);
    }

    /**
     * 处理缺省规则，一个资源下只能有一个缺省规则
     * @param data
     */
    private void handleDefaulted(FileStorage data) {
        if (Boolean.TRUE.equals(data.getDefaulted())) {
            boolean update = update(
                    Wrappers.<FileStorage>lambdaUpdate().set(FileStorage::getDefaulted, false)
            );
            if (update) {
                Cache cache = cacheManager.getCache(GeneralCacheKey.FILE_STORAGE);
                if (cache != null) {
                    cache.clear();
                }
            }
//            AssertUtil.isTrue(update, "设置缺省规则失败");
        }
    }

    @Cacheable(value = GeneralCacheKey.FILE_STORAGE, key = "'default'")
    @Override
    public FileStorage getDefaulted() {
        return getFirst(
                Wrappers.<FileStorage>lambdaQuery()
                        .orderByDesc(FileStorage::getDefaulted)
        );
    }

    @Override
    public void connectionTest(FileStorage fileStorage) {
        if (fileStorage.getId() != null && (fileStorage.getAccessKey() == null || fileStorage.getSecretKey() == null)) {
            FileStorage storage = getById(fileStorage.getId());
            if (fileStorage.getAccessKey() == null) {
                fileStorage.setAccessKey(storage.getAccessKey());
            }
            if (fileStorage.getSecretKey() == null) {
                fileStorage.setSecretKey(storage.getSecretKey());
            }
        }
        fileStorage.setStatus(FileStorageStatusEnum.normal);
        FileTemplate.create(fileStorage).test();
    }

}
